﻿using CSRedis;

namespace Magic.Redis;

/// <summary>
/// 定义标准的redis客户端访问接口。
/// </summary>
public interface IRedisClient
{
	/// <summary>
	/// 初始化redis客户端；
	/// </summary>
	/// <param name="connectionString"></param>
	void Initialization(string connectionString);

	#region Key
	/// <summary>
	/// 删除传入的 key，命令：del {key}
	/// </summary>
	/// <param name="key">要移除的key</param>
	/// <returns>返回<see cref="bool"/>表示移除成功或失败，key不存在时将返回<code>false</code></returns>
	bool KeyDelete(string key);

	/// <summary>
	/// （异步的）删除传入的 key，命令：del {key}
	/// </summary>
	/// <param name="key">要移除的key</param>
	/// <returns>返回<see cref="bool"/>表示移除成功或失败，key不存在时将返回<code>false</code></returns>
	Task<bool> KeyDeleteAsync(string key);

	/// <summary>
	/// 返回指定的key是否存在，命令：exists {key}
	/// </summary>
	/// <param name="key"></param>
	/// <returns>返回<see cref="bool"/>表示key是否存在。</returns>
	bool KeyExists(string key);

	/// <summary>
	/// （异步的）返回指定的key是否存在，命令：exists {key}
	/// </summary>
	/// <param name="key"></param>
	/// <returns>返回<see cref="bool"/>表示key是否存在。</returns>
	Task<bool> KeyExistsAsync(string key);

	/// <summary>
	/// 为指定的 key 设置过期时间点
	/// </summary>
	/// <param name="key">要设定的 key</param>
	/// <param name="expiry">可选参数，过期时间<see cref="DateTime"/>，在该时间之后，key 会过期，不传递将会设置为即刻过期。</param>
	/// <returns>返回<see cref="bool"/>表示是否设定成功，key不存在时将返回<code>false</code>。</returns>
	bool KeyExpireAt(string key, DateTime? expiry = null);

	/// <summary>
	/// （异步的）为指定的 key 设置过期时间点
	/// </summary>
	/// <param name="key">要设定的 key</param>
	/// <param name="expiry">可选参数，过期时间<see cref="DateTime"/>，在该时间之后，key 会过期，不传递将会设置为即刻过期。</param>
	/// <returns>返回<see cref="bool"/>表示是否设定成功，key不存在时将返回<code>false</code>。</returns>
	Task<bool> KeyExpireAtAsync(string key, DateTime? expiry = null);
	#endregion End Key

	#region String 

	/// <summary>
	/// 返回指定的 key 的string类型数据，key不存在时，将返回默认值
	/// </summary>
	/// <typeparam name="T">返回的类型</typeparam>
	/// <param name="key"></param>
	/// <returns>返回获取到的数据<see cref="StringGet{T}(string)"/></returns>
	T StringGet<T>(string key);

	/// <summary>
	/// 异步的返回指定的redis key的string类型数据，key不存在时，将返回默认值
	/// </summary>
	/// <typeparam name="T">返回的类型</typeparam>
	/// <param name="key"></param>
	/// <returns></returns>
	Task<T> StringGetAsync<T>(string key);

	/// <summary>
	/// 设置string类型的redis数据
	/// </summary>
	/// <typeparam name="T">传入的value的类型</typeparam>
	/// <param name="key"></param>
	/// <param name="value"></param>
	/// <param name="expiry">（滑动过期）过期时间间隔<see cref="TimeSpan"/></param>
	/// <returns></returns>
	bool StringSet<T>(string key, T value, TimeSpan? expiry = null);

	/// <summary>
	/// 异步的设置string类型的redis数据
	/// </summary>
	/// <typeparam name="T">传入的value的类型</typeparam>
	/// <param name="key"></param>
	/// <param name="value"></param>
	/// <param name="expiry">（滑动过期）过期时间间隔<see cref="TimeSpan"/></param>
	/// <returns></returns>
	Task<bool> StringSetAsync<T>(string key, T value, TimeSpan? expiry = null);

	/// <summary>
	/// 返回指定的redis key对应的string数据的长度，key不存在将返回默认值
	/// </summary>
	/// <param name="key"></param>
	/// <returns>返回<see cref="long"/>类型的数据的长度</returns>
	long StringLength(string key);

	/// <summary>
	/// 异步的返回指定的redis key对应的string数据的长度，key不存在将返回默认值
	/// </summary>
	/// <param name="key"></param>
	/// <returns>返回<see cref="long"/>类型的数据的长度</returns>
	Task<long> StringLengthAsync(string key);

	/// <summary>
	/// 计数器，计数并返回当前数值
	/// </summary>
	/// <param name="key"></param>
	/// <param name="value"></param>
	/// <returns></returns>
	long StringIncrement(string key, long value = 1L);

	/// <summary>
	/// 异步的计数器，计数并返回当前数值
	/// </summary>
	/// <param name="key"></param>
	/// <param name="value"></param>
	/// <returns></returns>
	Task<long> StringIncrementAsync(string key, long value = 1L);
	#endregion End String

	#region Hash

	/// <summary>
	/// 设置redis hash值
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="field"></param>
	/// <param name="key"></param>
	/// <param name="value"></param>
	/// <returns></returns>
	bool HashSet<T>(string key, string field, T value);

	/// <summary>
	/// 异步的设置redis hash值
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="field"></param>
	/// <param name="key"></param>
	/// <param name="value"></param>
	/// <returns></returns>
	Task<bool> HashSetAsync<T>(string key, string field, T value);

	/// <summary>
	/// 获取redis hash字段的值
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <param name="field"></param>
	/// <returns></returns>
	T HashGet<T>(string key, string field);

	/// <summary>
	/// 异步的获取redis hash字段的值
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <param name="field"></param>
	/// <returns></returns>
	Task<T> HashGetAsync<T>(string key, string field);

	/// <summary>
	/// 移除指定的redis hash字段
	/// </summary>
	/// <param name="key"></param>
	/// <param name="field"></param>
	/// <returns></returns>
	bool HashDelete(string key, string field);

	/// <summary>
	/// 异步的移除指定的redis hash字段
	/// </summary>
	/// <param name="key"></param>
	/// <param name="field"></param>
	/// <returns></returns>
	Task<bool> HashDeleteAsync(string key, string field);

	/// <summary>
	/// 返回指定的redis hash字段是否存在
	/// </summary>
	/// <param name="key"></param>
	/// <param name="field"></param>
	/// <returns></returns>
	bool HashExists(string key, string field);

	/// <summary>
	/// 异步的返回指定的redis hash字段是否存在
	/// </summary>
	/// <param name="key"></param>
	/// <param name="field"></param>
	/// <returns></returns>
	Task<bool> HashExistsAsync(string key, string field);
	#endregion End Hash

	#region List

	/// <summary>
	/// 获取指定的索引位置的redis list数据
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <param name="index"></param>
	/// <returns></returns>
	T ListGetByIndex<T>(string key, long index);

	/// <summary>
	/// 异步的获取指定的索引位置的redis list数据
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <param name="index"></param>
	/// <returns></returns>
	Task<T> ListGetByIndexAsync<T>(string key, long index);

	/// <summary>
	/// 返回redis list的长度
	/// </summary>
	/// <param name="key"></param>
	/// <returns></returns>
	long ListLength(string key);

	/// <summary>
	/// 异步的返回redis list的长度
	/// </summary>
	/// <param name="key"></param>
	/// <returns></returns>
	Task<long> ListLengthAsync(string key);

	/// <summary>
	/// 返回redis list最左侧的一个元素，并从redis list中移除
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <returns></returns>
	T ListLeftPop<T>(string key);

	/// <summary>
	/// 异步的返回redis list最左侧的一个元素，并从redis list中移除
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <returns></returns>
	Task<T> ListLeftPopAsync<T>(string key);

	/// <summary>
	/// 向redis list的最左侧写入一个元素
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <param name="value"></param>
	/// <returns></returns>
	long ListLeftPush<T>(string key, T value);

	/// <summary>
	/// 异步的向redis list的最左侧写入一个元素
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <param name="value"></param>
	/// <returns></returns>
	Task<long> ListLeftPushAsync<T>(string key, T value);

	/// <summary>
	/// 返回redis list最右侧的一个元素，并从redis list中移除
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <returns></returns>
	T ListRightPop<T>(string key);

	/// <summary>
	/// 异步的返回redis list最右侧的一个元素，并从redis list中移除
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <returns></returns>
	Task<T> ListRightPopAsync<T>(string key);

	/// <summary>
	/// 向redis list的最右侧写入一个元素
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <param name="value"></param>
	/// <returns></returns>
	long ListRightPush<T>(string key, T value);

	/// <summary>
	/// 异步的向redis list的最右侧写入一个元素
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <param name="value"></param>
	/// <returns></returns>
	Task<long> ListRightPushAsync<T>(string key, T value);
	#endregion End List

	#region Set 

	/// <summary>
	/// 向redis set中写入数据
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <param name="value"></param>
	/// <returns></returns>
	bool SetAdd<T>(string key, T value);

	/// <summary>
	/// 异步的向redis set中写入数据
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <param name="value"></param>
	/// <returns></returns>
	Task<bool> SetAddAsync<T>(string key, T value);

	///// <summary>
	///// 返回redis set中是否包含指定的元素
	///// </summary>
	///// <typeparam name="T"></typeparam>
	///// <param name="key"></param>
	///// <param name="value"></param>
	///// <returns></returns>
	//bool SetContains<T>(string key, T value);

	///// <summary>
	///// 异步的返回redis set中是否包含指定的元素
	///// </summary>
	///// <typeparam name="T"></typeparam>
	///// <param name="key"></param>
	///// <param name="value"></param>
	///// <returns></returns>
	//Task<bool> SetContainsAsync<T>(string key, T value);

	///// <summary>
	///// 返回redis set的长度
	///// </summary>
	///// <param name="key"></param>
	///// <returns></returns>
	//long SetLength(string key);

	///// <summary>
	///// 异步的返回redis set的长度
	///// </summary>
	///// <param name="key"></param>
	///// <returns></returns>
	//Task<long> SetLengthAsync(string key);

	/// <summary>
	/// 从redis set中移除指定的元素
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <param name="field"></param>
	/// <returns></returns>
	bool SetRemove<T>(string key, T field);

	/// <summary>
	/// 异步的从redis set中移除指定的元素
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <param name="field"></param>
	/// <returns></returns>
	Task<bool> SetRemoveAsync<T>(string key, T field);

	/// <summary>
	/// 从redis set中随机的返回一个元素，并从redis set中移除掉
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <returns></returns>
	T SetPop<T>(string key);

	/// <summary>
	/// 异步的从redis set中随机的返回一个元素，并从redis set中移除掉
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <returns></returns>
	Task<T> SetPopAsync<T>(string key);
	#endregion End Set

	#region SortedSet
	/// <summary>
	/// 向redis sortedset中写入一个元素
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <param name="value"></param>
	/// <param name="score"></param>
	/// <returns></returns>
	bool SortedSetAdd<T>(string key, T value, decimal score);

	/// <summary>
	/// 异步的向redis sortedset中写入一个元素
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <param name="value"></param>
	/// <param name="score"></param>
	/// <returns></returns>
	Task<bool> SortedSetAddAsync<T>(string key, T value, decimal score);

	///// <summary>
	///// 返回redis sortedset的长度
	///// </summary>
	///// <param name="key"></param>
	///// <returns></returns>
	//long SortedSetLength(string key);

	///// <summary>
	///// 异步的返回redis sortedset的长度
	///// </summary>
	///// <param name="key"></param>
	///// <returns></returns>
	//Task<long> SortedSetLengthAsync(string key);

	/// <summary>
	/// 从redis sortedset中移除指定的元素
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <param name="field"></param>
	/// <returns></returns>
	bool SortedSetRemove<T>(string key, T field);

	/// <summary>
	/// 异步的从redis sortedset中移除指定的元素
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <param name="field"></param>
	/// <returns></returns>
	Task<bool> SortedSetRemoveAsync<T>(string key, T field);

	/// <summary>
	/// 返回redis sortedset中分数值最低的元素，并从redis sortedset中移除掉
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <returns></returns>
	T SortedSetPopMin<T>(string key);

	/// <summary>
	/// 异步的返回redis sortedset中分数值最低的元素，并从redis sortedset中移除掉
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="key"></param>
	/// <returns></returns>
	Task<T> SortedSetPopMinAsync<T>(string key);
	#endregion End SortedSet

	#region Publish And Subscribe
	/// <summary>
	/// 订阅消息
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="channel"></param>
	/// <param name="handler"></param>
	void Subscribe<T>(string channel, Action<T> handler);

	///// <summary>
	///// 异步的订阅消息
	///// </summary>
	///// <typeparam name="T"></typeparam>
	///// <param name="channel"></param>
	///// <param name="handler"></param>
	///// <returns></returns>
	//Task SubscribeAsync<T>(string channel, Action<T> handler);

	/// <summary>
	/// 发布消息
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="channel"></param>
	/// <param name="message"></param>
	/// <returns></returns>
	long Publish<T>(string channel, T message);

	/// <summary>
	/// 异步的发布消息
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="channel"></param>
	/// <param name="message"></param>
	/// <returns></returns>
	Task<long> PublishAsync<T>(string channel, T message);
	#endregion End Publish And Subscribe

	#region Lock
	/// <summary>
	/// 获取分布式锁操作，返回false表示获取锁失败。
	/// <para>当前锁会在传入的expires之后过期，自动释放锁；</para>
	/// <para>想强制释放锁，请调用返回值<see cref="CSRedisClientLock"/>的方法：<see cref="CSRedisClientLock.Unlock()"/>；</para>
	/// <para>不在同一个上下文时，释放锁，请调用：<see cref="IRedisClient.Unlock(string, string)"/></para>
	/// </summary>
	/// <param name="key"></param>
	/// <param name="value"></param>
	/// <param name="expires">锁的超时时间，过期后强制释放锁</param>
	/// <returns></returns>
	CSRedisClientLock Lock(string key, string value, TimeSpan expires);

	/// <summary>
	/// 释放锁
	/// </summary>
	/// <param name="key"></param>
	/// <param name="value"></param>
	/// <returns></returns>
	bool Unlock(string key, string value);

	///// <summary>
	///// 异步的获取分布式锁操作，返回false表示获取锁失败。
	///// </summary>
	///// <param name="key"></param>
	///// <param name="value"></param>
	///// <param name="expires">锁的超时时间，过期后强制释放锁</param>
	///// <returns></returns>
	//Task<bool> LockTakeAsync(string key, string value, TimeSpan expires);

	///// <summary>
	///// 释放分布式锁。
	///// </summary>
	///// <param name="key"></param>
	///// <param name="value"></param>
	///// <returns></returns>
	//bool LockRelease(string key, string value);

	///// <summary>
	///// 异步的释放分布式锁。
	///// </summary>
	///// <param name="key"></param>
	///// <param name="value"></param>
	///// <returns></returns>
	//Task<bool> LockReleaseAsync(string key,string value);
	#endregion END Lock
}
